RichEditor.render   B
last analyzed

Complexity

Conditions 1

Size

Total Lines 81
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 71
dl 0
loc 81
rs 7.949
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
/**
2
 * Rich WYSIWYG Editor
3
 *
4
 * @author kyungmi.k
5
 * @since 1.0.0
6
 */
7
8
import React from 'react';
9
import PropTypes from 'prop-types';
10
import Draft from 'draft-js';
11
import { stateToHTML } from 'draft-js-export-html';
12
import {
13
  Button,
14
  ButtonToolbar,
15
  ButtonGroup,
16
} from 'react-bootstrap';
17
import config from '../../config/client.config';
18
19
const Editor = Draft.Editor;
20
const EditorState = Draft.EditorState;
21
const ContentState = Draft.ContentState;
22
const RichUtils = Draft.RichUtils;
23
24
const DEFAULT_BUTTON = Object.freeze({
25
  BOLD: false,
26
  ITALIC: false,
27
  UNDERLINE: false,
28
  STRIKETHROUGH: false,
29
  'unordered-list-item': false,
30
  'ordered-list-item': false,
31
});
32
33
export default class RichEditor extends React.Component {
34
  constructor(props) {
35
    super(props);
36
    let editorState;
37
    if (props.value) {
38
      const blocks = Draft.convertFromHTML(props.value);
39
      const contentState = ContentState.createFromBlockArray(blocks.contentBlocks, blocks.entityMap);
40
      editorState = EditorState.createWithContent(contentState);
41
    } else {
42
      editorState = EditorState.createEmpty();
43
    }
44
    this.state = {
45
      editorState,
46
      buttons: DEFAULT_BUTTON,
47
    };
48
49
    this.onToggleBlockType = blockType => this.onChange(RichUtils.toggleBlockType(this.state.editorState, blockType));
50
    this.onToggleInlineStyle = inlineStyle => this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, inlineStyle));
51
52
    this.onTab = (e) => {
53
      const maxDepth = 4;
54
      this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth));
55
    };
56
  }
57
58
  onChange(editorState) {
59
    this.setState({ editorState });
60
    this.changeButtonState(this.getCurrent(editorState));
61
    // TODO remove replace(/\n/g, '') after this PR(sstur/draft-js-export-html#66) is merged
62
    this.props.onChange(stateToHTML(editorState.getCurrentContent(), { prettyPrint: false }).replace(/\n/g, ''));
63
  }
64
65
  getCurrent(editorState) {
66
    const selection = editorState.getSelection();
67
    const blockType = editorState
68
      .getCurrentContent()
69
      .getBlockForKey(selection.getStartKey())
70
      .getType();
71
    const inlineStyles = editorState.getCurrentInlineStyle().toArray();
72
    return [].concat(blockType, inlineStyles);
73
  }
74
75
  changeButtonState(current) {
76
    const newButtons = Object.assign({}, DEFAULT_BUTTON);
77
    current.forEach((c) => { newButtons[c] = true; });
78
    this.setState({ buttons: newButtons });
79
  }
80
81
  setContent(html) {
82
    let editorState;
83
    if (html) {
84
      const blocks = Draft.convertFromHTML(html);
85
      const contentState = ContentState.createFromBlockArray(blocks.contentBlocks, blocks.entityMap);
86
      editorState = EditorState.createWithContent(contentState);
87
    } else {
88
      editorState = EditorState.createEmpty();
89
    }
90
    this.onChange(editorState);
91
  }
92
93
  render() {
94
    return (
95
      <div className="editor-root">
96
        <ButtonToolbar>
97
          <ButtonGroup style={{ marginLeft: 0 }}>
98
            <Button
99
              bsSize="small"
100
              active={this.state.buttons.BOLD}
101
              onMouseDown={() => this.onToggleInlineStyle('BOLD')}
102
            >
103
              <i className="fa fa-bold" aria-hidden="true" />
104
            </Button>
105
          </ButtonGroup>
106
          <ButtonGroup>
107
            <Button
108
              bsSize="small"
109
              active={this.state.buttons.ITALIC}
110
              onMouseDown={() => this.onToggleInlineStyle('ITALIC')}
111
              disabled={!config.editor.supportEnhancedFormat}
112
            >
113
              <i className="fa fa-italic" aria-hidden="true" />
114
            </Button>
115
            <Button
116
              bsSize="small"
117
              active={this.state.buttons.UNDERLINE}
118
              onMouseDown={() => this.onToggleInlineStyle('UNDERLINE')}
119
              disabled={!config.editor.supportEnhancedFormat}
120
            >
121
              <i className="fa fa-underline" aria-hidden="true" />
122
            </Button>
123
            <Button
124
              bsSize="small"
125
              active={this.state.buttons.STRIKETHROUGH}
126
              onMouseDown={() => this.onToggleInlineStyle('STRIKETHROUGH')}
127
              disabled={!config.editor.supportEnhancedFormat}
128
            >
129
              <i className="fa fa-strikethrough" aria-hidden="true" />
130
            </Button>
131
            <Button
132
              bsSize="small"
133
              active={this.state.buttons['unordered-list-item']}
134
              onMouseDown={() => this.onToggleBlockType('unordered-list-item')}
135
              disabled={!config.editor.supportEnhancedFormat}
136
            >
137
              <i className="fa fa-list-ul" aria-hidden="true" />
138
            </Button>
139
            <Button
140
              bsSize="small"
141
              active={this.state.buttons['ordered-list-item']}
142
              onMouseDown={() => this.onToggleBlockType('ordered-list-item')}
143
              disabled={!config.editor.supportEnhancedFormat}
144
            >
145
              <i className="fa fa-list-ol" aria-hidden="true" />
146
            </Button>
147
          </ButtonGroup>
148
          { !config.editor.supportEnhancedFormat &&
149
            <div
150
              style={{
151
                width: '160px',
152
                height: '30px',
153
                position: 'relative',
154
                left: '36px',
155
                backgroundColor: 'rgba(228, 228, 228, 0.6)',
156
                color: '#8e8e8e',
157
                textAlign: 'center',
158
                lineHeight: '30px',
159
              }}
160
            >
161
              <div style={{ position: 'absolute', width: '100%', fontSize: '12px' }}>추후 지원 예정</div>
162
            </div>
163
          }
164
        </ButtonToolbar>
165
        <Editor
166
          className="RichEditor-editor"
167
          editorState={this.state.editorState}
168
          onChange={s => this.onChange(s)}
169
          onTab={e => this.onTab(e)}
170
          placeholder={this.props.placeholder}
171
        />
172
      </div>
173
    );
174
  }
175
}
176
177
RichEditor.propTypes = {
178
  onChange: PropTypes.func,
179
  value: PropTypes.string,
180
  placeholder: PropTypes.string,
181
};
182
RichEditor.defaultProps = {
183
  onChange: () => {},
184
  value: '',
185
  placeholder: '',
186
};
187